<template>
    <div>
        <div class="loading" v-if="isLoading">
            <div >
                <div style="width: 34px;height: 34px">
                    <img src="../../static/images/loading.gif" alt="" style="width: 100%">
                </div>
                <div>{{ $t("lab_loading") }}</div><!--加载中...-->
            </div>
        </div>
        <!--您的账号已在其他地方登陆，您已经被挤下线-->
        <!--若非本人操作，请联系管理员-->
        <van-dialog
        v-model="errorsTip"
        :title="$t('lab_login_tips_7')"
        :message="$t('lab_login_tips_8')"
        :confirm-button-text="$t('sure')"
        >
        </van-dialog>
        <!--令牌已过期,请重新登录（3秒后自动跳到登陆页面）-->
        <van-dialog
        v-model="errorsToken"
        :title="$t('lab_login_tips_9')"
        :confirm-button-text="$t('sure')"
        @confirm="$router.push({path: '/'})"
        >
        </van-dialog>
    </div>
</template>

<script>
import axios from 'axios';
import { Toast } from 'vant';
import { clearLoginStorage } from '../utils/tools';
export default {
    name: 'loading',
    data() {
        return {
            errorsTip: false,
            errorsToken: false,
            isLoading: false
        };
    },
    components: {vanToast: Toast},
    created() {
        let berferLoad = []; //请求前的数据
        let afterLoad = []; //响应后的数据
        let loadingEnd = () => {
            berferLoad = [];
            afterLoad = [];
        };
        let cancelToken = axios.CancelToken;
        let source = cancelToken.source();
        const cancelTokenMap = new Set();
        //axios全局请求拦截器
        axios.interceptors.request.use((config) => {
            berferLoad.push(config);
            if (this.$store.state.config.plus && !config.url.includes('http://') && !config.url.includes('https://')) { //APP接口配置
                config.url = this.$store.getters.getAppUrl + config.url;
            }
            if (window.localStorage.getItem('token')) {
                config.headers.common.token = window.localStorage.getItem('token');
            }
            config.headers.common.developer = 'mobile';
            let responseData = {...config.params} || {};
            config.params = {
                t: new Date().getTime(),
                ...config.params
            };
            config.cancelToken = source.token;
            // 生成请求的唯一标识符
            const requestKey = `${config.method}-${config.url}-${JSON.stringify(responseData)}`;
            // 如果发送的请求已存在，取消重复请求
            // 添加请求到 Set 中
            if (cancelTokenMap.has(requestKey)) {
                return Promise.reject(new axios.Cancel({config, responseData, errCode: 'REPEATED_REQUEST', errMsg: ''}));
            }
            cancelTokenMap.add(requestKey);
            return config;
        }, (error) => {
            loadingEnd();
            return Promise.reject(error);
        });
        //axios全局响应拦截器
        axios.interceptors.response.use((response) => {
            afterLoad.push(response);
            if (response.data && response.data.errCode === 'ERROR_LANDED_SOMEWHERE_ELSE') {
                this.errorsTip = true;
                this.$router.push({path: '/'});
            }
            if (response.data && (response.data.errCode === 'ERROR_TOKEN_INVALID') && response.config.url.indexOf('/app/login') < 0) {
                source.cancel(this.$t('lab_login_tips_10')); //请求失败请重新登入
                this.errorsToken = true;
                window.sessionStorage.clear();
                clearLoginStorage();
                if (!this.timer) {
                    this.timer = setInterval(() => {
                        clearInterval(this.timer);
                        this.timer = null;
                        this.errorsToken = false;
                        //跳转的页面写在此处
                        this.$router.push({path: '/'});
                    }, 3000);
                    if (this.errorsToken === false) {
                        this.$router.push({path: '/'});
                    }
                }
                cancelToken = axios.CancelToken;
                source = cancelToken.source();
                return response;
            }
            //加载全部完成后
            if (afterLoad.length === berferLoad.length) {
                loadingEnd();
            }
            // 从请求拦截器中移除已完成的请求
            let responseData = {...response.config.params} || {};
            delete responseData.t;
            const requestKey = `${response.config.method}-${response.config.url}-${JSON.stringify(responseData)}`;
            // 从请求 Set 中移除已完成的请求
            cancelTokenMap.delete(requestKey);
            return response;
        }, (error) => {
            var errTip = this.$t('unknown_error');
            // 如果是请求被取消的错误，忽略它
            if (axios.isCancel(error)) {
                //对响应错误做点什么
                cancelToken = axios.CancelToken;
                source = cancelToken.source();
                loadingEnd();
                // 从请求拦截器中移除出错的请求
                const requestKey = `${error.message.config.method}-${error.message.config.url}-${JSON.stringify(error.message.responseData)}`;
                cancelTokenMap.delete(requestKey);
                // 请求重复不提示
                // if (error.message && error.message.errCode && error.message.errCode === 'REPEATED_REQUEST') {
                //     Toast.fail({
                //         type: 'html',
                //         message: this.$t('request_repeat') // 重复请求
                //     });
                // }
                return new Promise(() => {});
            }
            const errors = error.response;
            const { data, status } = error.response;
            if (error.response && error.response.data && error.response.data.errCode === 'ERROR_TOKEN_INVALID' && error.response.config.url.indexOf('/app/login') < 0) {
                source.cancel(this.$t('lab_login_tips_10')); //请求失败请重新登入
                this.errorsToken = true;
                window.sessionStorage.clear();
                clearLoginStorage();
                if (!this.timer) {
                    this.timer = setInterval(() => {
                        clearInterval(this.timer);
                        this.timer = null;
                        this.errorsToken = false;
                        //跳转的页面写在此处
                        this.$router.push({path: '/loginIndex'});
                        this.$emit('openError', false);
                    }, 3000);
                    if (this.errorsToken === false) {
                        this.$emit('openError', false);
                        this.$router.push({path: '/loginIndex'});
                    }
                }
            } else { // 错误请求提示国际化
                if (errors[status] && !data.errMsg) {
                    errTip = errors[status];
                } else {
                    if (status === 404 || status === 413 || status === 504 || status === 502) {
                        errTip = this.$t('requestError.server_error');
                    } else {
                        errTip = this.checkError(data);
                    }
                    switch (error.response.status) {
                    case 401: {
                        errTip = this.$t('timeout');
                        break;
                    }
                    }
                }
            }
            if (errTip) {
                Toast.fail({
                    type: 'html',
                    message: errTip
                });
            }
            //对响应错误做点什么
            cancelToken = axios.CancelToken;
            source = cancelToken.source();
            loadingEnd();
            // 从请求拦截器中移除出错的请求
            let responseData = {...error.response.config.params} || {};
            delete responseData.t;
            const requestKey = `${error.response.config.method}-${error.response.config.url}-${JSON.stringify(responseData)}`;
            cancelTokenMap.delete(requestKey);
            // return Promise.reject(error.response.data);
            return Promise.reject(error);
        });
    },
    methods: {
        /**
         * 检查错误格式 后端返回错误信息的标准格式
         * @param data =  {
         *    "errCode": "TRAINING_ADMIN_COURSE_CONFLICT_MSG",
         *    "errMsg": "以下课程编码的课程管理员与培训中心管理员冲突",
         *    "errDetail": [
         *       "chiu培训中心课程0105chiu培训",
         *       "chiu培训中心课程0108",
         *       "公共课0108"
         *     ]
         * }
         * @returns {*}
         */
        checkError(data) {
            if (data.constructor === Object) {
                let test = '';
                if (data.errDetail && data.errDetail.length > 0) {
                    let error = '';
                    if (data.errMsg) {
                        error = data.errMsg;
                        test += error;
                        test += '<br>';
                    }
                    for (let i = 0; i < data.errDetail.length; i++) {
                        test += data.errDetail[i] + '<br>';
                    }
                } else {
                    test = data.errMsg;
                }
                return test;
            } else {
                return data;
            }
        }
    }
};
</script>

<style scoped lang="less">
.loading{
    position: fixed;
    width: 100%;
    height: 100%;
    z-index: 1;
   /* background: #ffffff;*/
    &>div{
        width: 118px;
        height: 118px;
        background: rgba(0,0,0,.5);
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        margin: auto;
        color: #ffffff;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
        border-radius: 16px;
        &>div:first-child{
            margin-bottom: 10px;
        }
    }
}
</style>
